package com.xinthe.krisco.utils;
import java.io.IOException;
import java.rmi.RemoteException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import com.yantra.interop.japi.YIFApi;
import com.yantra.interop.japi.YIFClientCreationException;
import com.yantra.interop.japi.YIFClientFactory;
import com.yantra.yfc.dom.YFCDocument;
import com.yantra.yfs.japi.YFSEnvironment;
import com.yantra.yfs.japi.YFSException;

/**
 * 
 * @author vepurini
 *
 */


public class XintheUtil {
	/**
	 * Gets the child element with the given name. If not found returns null.
	 * This method returns null if either parent is null or child name is void.
	 * @param parentEle parentEle
	 * @param childName childName
	 * @return Element
	 */
	public static Element getChildElement(Element parentEle, String childName) {
		return getChildElement(parentEle, childName, false);
	}


	/**
	 * Gets the child element with the given name. If not found:
	 *     1) a new element will be created if "createIfNotExists" is true.
	 *     OR
	 *     2) null will be returned if "createIfNotExists" is false.
	 * This method returns null if either parent is null or child name is void.
	 * 	@param parentEle parentEle
	 *   @param childName childName
	 *   @param createIfNotExists createIfNotExists flag
	 *   @return Element
	 */
	public static Element getChildElement(Element parentEle, String childName, boolean createIfNotExists) {

		Element child = null;
		if (parentEle != null && childName !=null) {
			for (Node n = parentEle.getFirstChild(); n != null; n = n.getNextSibling()) {
				if (n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().equals(childName)) {
					return (Element) n;
				}
			}
			if (createIfNotExists) {
				child = createChild(parentEle, childName);

			}
		}
		return child;
	}

	/**
	 * Creates a child element under the parent element with given child name. Returns the newly created child element.
	 * This method returns null if either parent is null or child name is void.
	 * @param parentEle parentElement
	 * @param childName childName
	 * @return Element
	 */
	public static Element createChild(Element parentEle, String childName) {
		Element child = null;
		if (parentEle != null && !isVoid(childName)) {
			child = parentEle.getOwnerDocument().createElement(childName);
			parentEle.appendChild(child);
		}
		return child;
	}

	/**
	 * Utility method to check if a given object is void (just null check).
	 * @param obj Object for void check.
	 * @return true if the given object is null.
	 * <p></p>
	 */
	public static boolean isVoid(Object obj) {
		//return (obj == null) ? true : false;
		boolean retVal = false;
		if (obj == null) {
			retVal = true;

		}
		return retVal;
	}

	/**
	 * This method rounds of the double value to two decimal points.
	 * If the decimal point is less than 2 then it will make it to 
	 * 2 decimal points
	 * @param stringVal
	 * @return
	 */
	/*public static String roundTwoDecimals(String stringVal) {
		if(!isVoid(stringVal)){
			DecimalFormat dfRound = new DecimalFormat( NGPOSConstants.DECIMAL_ROUND_FORMAT);
			DecimalFormat twoDForm = new DecimalFormat(NGPOSConstants.DECIMAL_TWO_DIGITS);
			double roundedVal = Double.valueOf(dfRound.format(Double.parseDouble(stringVal)));
			stringVal = twoDForm.format(roundedVal);
		}
		return stringVal;
	}*/
	
	 /**
		*	Create a Document object with input as the name of document element.
		*
		*	@param docElementTag: the document element name.
		*	@throws ParserConfigurationException
	 * @throws IOException 
	 * @throws SAXException 
		*//*
		public static Document createDocument(String docElementTag)
		throws ParserConfigurationException
		{
	        DocumentBuilder dbdr = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document doc = dbdr.newDocument();
			Element ele = doc.createElement(docElementTag);
			doc.appendChild(ele);
			System.out.println(doc.toString());
			return doc;
		}*/

	public static Document createNewDocument(String documentElement) throws ParserConfigurationException, SAXException, IOException{
		DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
		DocumentBuilder  builder=builderFactory.newDocumentBuilder();
		Document document=builder.newDocument();
		Element ele=document.createElement(documentElement);
		document.appendChild(ele);
		return document;
	}
	
	 public static String getElementString(Element inputElement)
			    throws IllegalArgumentException, Exception {
			        // Validate input element
			        if (inputElement == null) {
			            throw new IllegalArgumentException(
			            "Input element cannot be null in "
			            + "XmlUtils.getElementString method");
			        }

			        // Import element content and construct Document
			        Document document = getDocument(inputElement, true);

			        // Convert document as element string
			        String xmlString = getXmlString(document);

			        // Remove Processing Instruction from xml string if exists
			        xmlString = removeProcessingInstruction(xmlString);

			        // Return result XML string
			        return xmlString;
			    }
	 
	 public static Document getDocument(Element inputElement, boolean deep)
	            throws IllegalArgumentException, ParserConfigurationException {
	        // Validate input element
	        if (inputElement == null) {
	            throw new IllegalArgumentException(
	            "Input element cannot be null in "
	            + "XmlUtils.getDocument method");
	        }

	        // Create a new document
	        Document outputDocument = getDocument();

	        // Import data from input element and
	        // set as root element for output document
	        outputDocument.appendChild(outputDocument
	        .importNode(inputElement, deep));

	        // return output document
	        return outputDocument;
	    }
	 
	 public static Document getDocument() throws ParserConfigurationException {
	        // Create a new Document Bilder Factory instance
	        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
	        .newInstance();

	        // Create new document builder
	        DocumentBuilder documentBuilder = documentBuilderFactory
	        .newDocumentBuilder();

	        // Create and return document object
	        return documentBuilder.newDocument();
	    }

	 public static String getXmlString(Document inputDocument)

			    throws IllegalArgumentException {

			        // Validate input document
			        if (inputDocument == null) {
			            throw new IllegalArgumentException(
			            "Input Document cannot be null in "
			            + "XmlUtils.getXMLString method");
			        }
			        return YFCDocument.getDocumentFor(inputDocument).getString();
			        /*StringWriter stringWriter = new StringWriter();
			        StreamResult output = new StreamResult(stringWriter);
			        DOMSource input = new DOMSource(inputDocument);

			        // transform using default text transformer
			        TransformerFactory xformFactory = TransformerFactory.newInstance();
			        Transformer idTransform = xformFactory.newTransformer();
			        idTransform.transform(input, output);

			        //Return xml string
			        return stringWriter.toString();*/
			    }
	 public static String removeProcessingInstruction(String xmlString)
			    throws IllegalArgumentException {
			        // Validate input XML string
			        if (xmlString == null) {
			            throw new IllegalArgumentException(
			            "Input XML string cannot be null in "
			            + "XmlUtils.removeProcessingInstruction method");
			        }

			        // Is input contains processing instruction
			        if ((xmlString.toLowerCase().trim().startsWith("<?xml"))) {
			            // Get the ending index of processing instruction
			            int processInstructionEndIndex = xmlString.indexOf("?>");

			            // If processing instruction ending found,
			            if (processInstructionEndIndex != -1) {
			                // Remove processing instruction
			                xmlString = xmlString.substring(processInstructionEndIndex + 2);
			            }
			        }

			        // Return XML string after update
			        return xmlString;
			    }
				
				
				/**
	 * 
	 * @param env
	 * @param apiName
	 * @param inputDoc
	 * @param templateName
	 * @return
	 * @throws YIFClientCreationException
	 * @throws YFSException
	 * @throws RemoteException
	 */
	public static Document callAPI(YFSEnvironment env,String apiName,
			Document inputDoc,String templateName) throws YIFClientCreationException, YFSException, RemoteException{
        Document outputDoc=null;
		if(templateName!= null){
			env.setApiTemplate(apiName, templateName);
		}
		YIFApi api=YIFClientFactory.getInstance().getApi();
		outputDoc=api.invoke(env, apiName, inputDoc);
		env.clearApiTemplate(apiName);
		return outputDoc;

	}
	/**
	 * 
	 * @param env
	 * @param apiName
	 * @param inputDoc
	 * @return
	 * @throws YFSException
	 * @throws RemoteException
	 * @throws YIFClientCreationException
	 */
	public static Document callAPI(YFSEnvironment env,String apiName,
			Document inputDoc) throws YFSException, RemoteException, YIFClientCreationException{
		Document outputDoc=null;
		String templateName=null;
		outputDoc=callAPI(env, apiName, inputDoc, templateName);
		return outputDoc;
	}
	/**
	 * 
	 * @param env
	 * @param serviceName
	 * @param inputDoc
	 * @param templateName
	 * @return
	 * @throws YIFClientCreationException
	 * @throws YFSException
	 * @throws RemoteException
	 */
	public static Document callService(YFSEnvironment env, String serviceName, Document inputDoc,String templateName) throws YIFClientCreationException, YFSException, RemoteException{
		Document outputDoc=null;
		if(templateName!=null){
			env.setApiTemplate(serviceName, serviceName);
		}
		YIFApi api=YIFClientFactory.getInstance().getApi();
		outputDoc=api.executeFlow(env, serviceName, inputDoc);
		env.clearApiTemplate(serviceName);
		return outputDoc;
	}
	/**
	 * 
	 * @param env
	 * @param serviceName
	 * @param inputDoc
	 * @return
	 * @throws YFSException
	 * @throws RemoteException
	 * @throws YIFClientCreationException
	 */
	public static Document callService(YFSEnvironment env, String serviceName,Document inputDoc) throws YFSException, RemoteException, YIFClientCreationException{
		Document outputDoc=null;
		String templateName=null;
		outputDoc=callService(env, serviceName, inputDoc, templateName);
		return outputDoc;
	}
}
